﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using CookingBg.Services.Proxies;

namespace CookingBg.Services
{
    [ServiceContract]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class RecipeService
    {
        #region General Recipe Methods

        [WebGet(UriTemplate = "GetRecipesCount", ResponseFormat = WebMessageFormat.Json)]
        public int GetRecipesCount()
        {
            var model = new Entities();
            return model.Recipes.Count();
        }

        [WebGet(UriTemplate = "GetRecipes?startIndex={startIndex}&count={count}&sorting={sorting}", ResponseFormat = WebMessageFormat.Json)]
        public IEnumerable<SmallListProxy> GetRecipes(int startIndex, int count, int sorting)
        {
            var model = new Entities();
            var recipes = from r in model.Recipes
                          select r;
                          
            switch (sorting)
            {
                case 1:
                    recipes = recipes.OrderByDescending(r => r.Date);
                    break;
                case 2:
                    recipes = recipes.OrderByDescending(r => r.CurrentRating);
                    break;
                default:
                    recipes = recipes.OrderBy(r => r.Title);
                    break;
            }

            var smallRecipesProxies = from r in recipes
                                      select new SmallListProxy
                                             {
                                                 ID = r.ID,
                                                 Title = r.Title,
                                                 SmallImageUrl = r.SmallImageUrl
                                             };
            return smallRecipesProxies.Skip(startIndex).Take(count);
        }

        [WebGet(UriTemplate = "SearchRecipes?search={search}", ResponseFormat = WebMessageFormat.Json)]
        public IEnumerable<SmallListProxy> SearchRecipes(string search)
        {
            var model = new Entities();
            search = search.ToUpper();
            var recipes = from r in model.Recipes
                          where r.Title.ToUpper().Contains(search) || r.Products.ToUpper().Contains(search)
                          orderby r.Title
                          select new SmallListProxy
                          {
                              ID = r.ID,
                              Title = r.Title,
                              SmallImageUrl = r.SmallImageUrl
                          };
            return recipes;
        }

        [WebGet(UriTemplate = "GetLatestRecipes", ResponseFormat = WebMessageFormat.Json)]
        public IEnumerable<SmallListProxy> GetLatestRecipes()
        {
            var model = new Entities();
            var recipes = from r in model.Recipes
                          orderby r.Date descending
                          select new SmallListProxy
                                     {
                                         ID = r.ID,
                                         Title = r.Title,
                                         SmallImageUrl = r.SmallImageUrl
                                     };
            return recipes.Take(10);
        }

        [WebGet(UriTemplate = "GetRecipesByProduct?products={products}", ResponseFormat = WebMessageFormat.Json)]
        public IEnumerable<SmallListProxy> GetRecipesByProduct(string products)
        {
            var model = new Entities();
            if (products != null)
            {
                var productArray = products.Split(',');
                var firstProduct = productArray[0].ToUpper();
                var recipes = from r in model.Recipes
                              where r.Products.ToUpper().Contains(firstProduct)
                              select new SmallListProxy
                              {
                                  ID = r.ID,
                                  Title = r.Title,
                                  SmallImageUrl = r.SmallImageUrl
                              };
                for (int i = 1; i < productArray.Length; i++)
                {
                    var product = productArray[i].ToUpper();
                    recipes = recipes.Intersect(from r in model.Recipes
                                                where r.Products.ToUpper().Contains(product)
                                                select new SmallListProxy
                                                {
                                                    ID = r.ID,
                                                    Title = r.Title,
                                                    SmallImageUrl = r.SmallImageUrl
                                                });
                }
                return recipes;
            }
            return null;
        }

        [WebGet(UriTemplate = "GetRecipe?id={id}&userId={userId}", ResponseFormat = WebMessageFormat.Json)]
        public BigRecipeProxy GetRecipe(int id, long userId)
        {
            var model = new Entities();
            var recipes = from r in model.Recipes
                          where r.ID == id
                          select new BigRecipeProxy
                          {
                              ID = r.ID,
                              Title = r.Title,
                              Products = r.Products,
                              Description = r.Description,
                              Notes = r.Notes,
                              ExternalUrl = r.ExternalUrl,
                              ImageUrls = r.RecipeImages.Select(ri => ri.ImageUrl),
                              IsFavorite = r.FavoriteRecipes.Any(fr => fr.UserId == userId),
                              Rating = r.UserRecipeRatings.FirstOrDefault(ur => ur.UserId == userId) == null ? 0 : r.UserRecipeRatings.FirstOrDefault(ur => ur.UserId == userId).Rating
                          };
            return recipes.FirstOrDefault();
        }

        [WebGet(UriTemplate = "GetRandomRecipe", ResponseFormat = WebMessageFormat.Json)]
        public BigRecipeProxy GetRandomRecipe()
        {
            var model = new Entities();
            var maxId = model.Recipes.Max(r => r.ID);
            var random = new Random();
            var id = random.Next(1, (int)maxId);
            var recipes = from r in model.Recipes
                          where r.ID == id
                          select new BigRecipeProxy
                          {
                              ID = r.ID,
                              Title = r.Title,
                              Products = r.Products,
                              Description = r.Description,
                              Notes = r.Notes,
                              ExternalUrl = r.ExternalUrl,
                              ImageUrls = r.RecipeImages.Select(ri => ri.ImageUrl)
                          };
            return recipes.FirstOrDefault();
        }


        #endregion

        #region Favorite Methods

        [WebInvoke(Method = "POST", UriTemplate = "SetFavorite", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json)]
        public void SetFavorite(long recipeId, long userId)
        {
            var model = new Entities();
            FavoriteRecipe favorite = new FavoriteRecipe();
            favorite.RecipeId = recipeId;
            favorite.UserId = userId;
            model.AddToFavoriteRecipes(favorite);
            model.SaveChanges();
        }

        [WebInvoke(Method = "POST", UriTemplate = "UnSetFavorite", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json)]
        public void UnSetFavorite(long recipeId, long userId)
        {
            var model = new Entities();
            var favorite = model.FavoriteRecipes.FirstOrDefault(fr => fr.RecipeId == recipeId && fr.UserId == userId);
            if (favorite != null)
            {
                model.DeleteObject(favorite);
                model.SaveChanges();
            }
        }

        [WebGet(UriTemplate = "GetFavoriteRecipes?userId={userId}", ResponseFormat = WebMessageFormat.Json)]
        public IEnumerable<SmallListProxy> GetFavoriteRecipes(long userId)
        {
            var model = new Entities();
            var recipes = from fr in model.FavoriteRecipes
                          join r in model.Recipes on fr.RecipeId equals r.ID
                          where fr.UserId == userId
                          orderby r.Title
                          select new SmallListProxy
                          {
                              ID = r.ID,
                              Title = r.Title,
                              SmallImageUrl = r.SmallImageUrl
                          };
            return recipes;
        }

        #endregion

        #region Comments Methods

        [WebInvoke(Method = "POST", UriTemplate = "AddRecipeComment", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json)]
        public void AddRecipeComment(long recipeId, long userId, string comment)
        {
            var model = new Entities();
            RecipeComment recipeComment = new RecipeComment();
            recipeComment.RecipeId = recipeId;
            recipeComment.UserId = userId;
            recipeComment.Comment = comment;
            recipeComment.Date = DateTime.Now;
            model.AddToRecipeComments(recipeComment);
            model.SaveChanges();
        }

        [WebInvoke(Method = "POST", UriTemplate = "EditRecipeComment", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json)]
        public void EditRecipeComment(long recipeCommentId, string comment)
        {
            var model = new Entities();
            var recipeComment = model.RecipeComments.FirstOrDefault(rc => rc.ID == recipeCommentId);
            if (recipeComment != null)
            {
                recipeComment.Comment = comment;
                model.SaveChanges();
            }
        }

        [WebInvoke(Method = "POST", UriTemplate = "RemoveRecipeComment", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json)]
        public void RemoveRecipeComment(long recipeCommentId)
        {
            var model = new Entities();
            var recipeComment = model.RecipeComments.FirstOrDefault(rc => rc.ID == recipeCommentId);
            if (recipeComment != null)
            {
                model.DeleteObject(recipeComment);
                model.SaveChanges();
            }
        }

        [WebGet(UriTemplate = "GetRecipeComments?recipId={recipId}", ResponseFormat = WebMessageFormat.Json)]
        public IEnumerable<RecipeCommentProxy> GetRecipeComments(long recipId)
        {
            var model = new Entities();
            return from rc in model.RecipeComments
                   where rc.RecipeId == recipId
                   select new RecipeCommentProxy
                              {
                                  ID = rc.ID,
                                  Comment = rc.Comment,
                                  UserName = rc.User.UserName,
                                  UserId = rc.UserId,
                                  CommentDate = rc.Date,
                              };
        }

        #endregion

        #region Ratings

        [WebInvoke(Method = "POST", UriTemplate = "SetRecipeRating", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json)]
        public void SetRecipeRating(long recipeId, long userId, double rating)
        {
            var model = new Entities();
            UserRecipeRating userRecipeRating = new UserRecipeRating();
            userRecipeRating.RecipeId = recipeId;
            userRecipeRating.UserId = userId;
            userRecipeRating.Rating = rating;
            model.AddToUserRecipeRatings(userRecipeRating);
            model.SaveChanges();
        }

        #endregion

    }
}